/*
 *   项目名称：rpc-demo
 *   文件名称：com.xiaolon.rpc.server.tcp.VertxTcpClient
 *
 *   创建人：  ZHOU XIAO LONG
 *   创建日期：2024/12/9
 *
 */
package com.xiaolon.rpc.server.tcp;

import cn.hutool.core.util.IdUtil;
import com.xiaolon.rpc.RpcApplication;
import com.xiaolon.rpc.model.RpcRequest;
import com.xiaolon.rpc.model.RpcResponse;
import com.xiaolon.rpc.model.ServiceMetaInfo;
import com.xiaolon.rpc.protocol.*;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/*
 * 类描述：VertxTcpClient
 * 客户端实现
 */
public class VertxTcpClient {

    /**
     * 发送请求
     * @param rpcRequest
     * @param serviceMetaInfo
     * @return
     */
    public static RpcResponse doResponse(RpcRequest rpcRequest, ServiceMetaInfo serviceMetaInfo) throws ExecutionException, InterruptedException {
        // 发送tcp请求
        Vertx vertx = Vertx.vertx();
        NetClient netClient = vertx.createNetClient();
        CompletableFuture<RpcResponse> responseFuture = new CompletableFuture<>();

        netClient.connect(serviceMetaInfo.getServicePort(), serviceMetaInfo.getServiceHost(),
                result->{
                    if(!result.succeeded()){
                        System.out.println("Failed to connect to TCP server");
                        return;
                    }

                    NetSocket socket = result.result();

                    // 发送数据
                    // 构造消息
                    ProtocolMessage<Object> protocolMessage = new ProtocolMessage<>();
                    ProtocolMessage.Header header = new ProtocolMessage.Header();
                    header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
                    header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
                    header.setSerializer((byte) ProtocolMessageSerializerEnum.getEnumByValue(RpcApplication.getRpcConfig().getSerializer()).getKey());
                    header.setType((byte) ProtocolMessageTypeEnum.REQUEST.getKey());

                    // 生成全局请求ID
                    header.setRequestId(IdUtil.getSnowflakeNextId());
                    protocolMessage.setHeader(header);
                    protocolMessage.setBody(rpcRequest);

                    // 编码请求
                    try{
                        Buffer encodeBuffer = ProtocolMessageEncoder.encode(protocolMessage);
                        socket.write(encodeBuffer);
                    }catch (IOException e){
                        throw new RuntimeException("协议编码错误");
                    }

                    // 接受响应
                    TcpBufferHandlerWrapper bufferHandlerWrapper = new TcpBufferHandlerWrapper(
                            buffer -> {
                                try{
                                    ProtocolMessage<RpcResponse> rpcResponseProtocolMessage = (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decode(buffer);
                                    responseFuture.complete(rpcResponseProtocolMessage.getBody());
                                }catch (IOException e){
                                    throw new RuntimeException("协议消息解码错误");
                                }
                            }
                    );
                    socket.handler(bufferHandlerWrapper);
                });
        RpcResponse rpcResponse = responseFuture.get();

        // 关闭连接
        netClient.close();
        return rpcResponse;
    }

}
